/*
 * @Description:
 * @Version:
 * @Author: Troubadour
 * @Date: 2023-01-17 20:30:41
 * @LastEditors: Troubadour
 * @LastEditTime: 2023-01-20 13:25:39
 */

#include "tft_gui.h"
#include "tft_font.h"

uint16_t BACK_COLOR;

/**
 * @function: TFT_GUI_Clear
 * @brief 指定颜色清屏
 * @param {uint16_t} color：颜色
 * @return {*}
 */
void TFT_GUI_Clear(uint16_t color)
{
    uint16_t i, j;
    TFT_Address_set(0, 0, TFT_WIDE - 1, TFT_HIGH - 1);
    for (i = 0; i < TFT_WIDE; i++)
    {
        for (j = 0; j < TFT_HIGH; j++)
        {
            TFT_Write_Data16(color);
        }
    }
}

/**
 * @function: TFT_GUI_DrawPoint
 * @brief 画点
 * @param {uint16_t} x：点x
 * @param {uint16_t} y：点y
 * @param {uint16_t} color：颜色
 * @return {*}
 */
void TFT_GUI_DrawPoint(uint16_t x, uint16_t y, uint16_t color)
{
    TFT_Address_set(x, y, x, y);
    TFT_Write_Data16(color);
}

/**
 * @function: TFT_GUI_Full
 * @brief 填充指定区域
 * @param {uint16_t} xsta：区域左上角x
 * @param {uint16_t} ysta：区域左上角y
 * @param {uint16_t} xend：区域右下角x
 * @param {uint16_t} yend：区域右下角y
 * @param {uint16_t} color：颜色
 * @return {*}
 */
void TFT_GUI_Full(uint16_t xsta, uint16_t ysta, uint16_t xend, uint16_t yend, uint16_t color)
{
    uint16_t i, j;
    TFT_Address_set(xsta, ysta, xend, yend);
    for (i = ysta; i <= yend; i++)
    {
        for (j = xsta; j <= xend; j++)
        {
            TFT_Write_Data16(color);
        }
    }
}

/**
 * @function: TFT_GUI_DrawLine
 * @brief 画线
 * @param {uint16_t} xsta：起点x
 * @param {uint16_t} ysta：起点y
 * @param {uint16_t} xend：终点x
 * @param {uint16_t} yend：终点y
 * @param {uint16_t} color：颜色
 * @return {*}
 */
void TFT_GUI_DrawLine(uint16_t xsta, uint16_t ysta, uint16_t xend, uint16_t yend, uint16_t color)
{
    uint16_t t;
    int xerr = 0, yerr = 0, delta_x, delta_y, distance;
    int incx, incy, uRow, uCol;

    delta_x = xend - xsta; // 计算坐标增量
    delta_y = yend - ysta;
    uRow = xsta;
    uCol = ysta;
    if (delta_x > 0)
        incx = 1; // 设置单步方向
    else if (delta_x == 0)
        incx = 0; // 垂直线
    else
    {
        incx = -1;
        delta_x = -delta_x;
    }
    if (delta_y > 0)
        incy = 1;
    else if (delta_y == 0)
        incy = 0; // 水平线
    else
    {
        incy = -1;
        delta_y = -delta_y;
    }
    if (delta_x > delta_y)
        distance = delta_x; // 选取基本增量坐标轴
    else
        distance = delta_y;

    for (t = 0; t <= distance + 1; t++) // 画线输出
    {
        TFT_GUI_DrawPoint(uRow, uCol, color); // 画点
        xerr += delta_x;
        yerr += delta_y;
        if (xerr > distance)
        {
            xerr -= distance;
            uRow += incx;
        }
        if (yerr > distance)
        {
            yerr -= distance;
            uCol += incy;
        }
    }
}

/**
 * @function: TFT_GUI_DrawRectangle
 * @brief 画一个矩形
 * @param {uint16_t} xsta：矩形左上角x
 * @param {uint16_t} ysta：矩形左上角y
 * @param {uint16_t} xend：矩形右下角x
 * @param {uint16_t} yend：矩形右下角y
 * @param {uint16_t} color：颜色
 * @return {*}
 */
void TFT_GUI_DrawRectangle(uint16_t xsta, uint16_t ysta, uint16_t xend, uint16_t yend, uint16_t color)
{
    TFT_GUI_DrawLine(xsta, ysta, xend, ysta, color);
    TFT_GUI_DrawLine(xsta, ysta, xsta, yend, color);
    TFT_GUI_DrawLine(xsta, yend, xend, yend, color);
    TFT_GUI_DrawLine(xend, ysta, xend, yend, color);
}

/**
 * @function: TFT_GUI_DrawCircle
 * @brief 画圆
 * @param {uint16_t} x0：圆心x
 * @param {uint16_t} y0：圆心y
 * @param {uint16_t} r：半径
 * @param {uint16_t} color：颜色
 * @return {*}
 */
void TFT_GUI_DrawCircle(uint16_t x0, uint16_t y0, uint16_t r, uint16_t color)
{
    int a, b;
    int di;
    a = 0;
    b = r;
    di = 3 - (r << 1); // 判断下个点位置的标志
    while (a <= b)
    {
        TFT_GUI_DrawPoint(x0 - b, y0 - a, color); // 3
        TFT_GUI_DrawPoint(x0 + b, y0 - a, color); // 0
        TFT_GUI_DrawPoint(x0 - a, y0 + b, color); // 1
        TFT_GUI_DrawPoint(x0 - b, y0 - a, color); // 7
        TFT_GUI_DrawPoint(x0 - a, y0 - b, color); // 2
        TFT_GUI_DrawPoint(x0 + b, y0 + a, color); // 4
        TFT_GUI_DrawPoint(x0 + a, y0 - b, color); // 5
        TFT_GUI_DrawPoint(x0 + a, y0 + b, color); // 6
        TFT_GUI_DrawPoint(x0 - b, y0 + a, color);
        a++;
        // 使用Bresenham算法画圆
        if (di < 0)
            di += 4 * a + 6;
        else
        {
            di += 10 + 4 * (a - b);
            b--;
        }
        TFT_GUI_DrawPoint(x0 + a, y0 + b, color);
    }
}

/**
 * @function: TFT_ShowNumber64
 * @brief 显示64x32字体的数字字符
 * @param {uint16_t} x：显示起点x
 * @param {uint16_t} y：显示起点y
 * @param {uint32_t} num：要显示的数字
 * @param {uint16_t} colorcolor：颜色
 * @return {*}
 */
void TFT_ShowChar64(uint16_t x, uint16_t y, uint8_t num, uint16_t color)
{
    uint16_t temp, pos, i;
    uint16_t offset = num * 256;

    if (x > TFT_WIDE - 32 || y > TFT_HIGH - 64)
        return;
    TFT_Address_set(x, y, x + 32 - 1, y + 64 - 1);   // 设置光标位置
    for (pos = 0; pos < 256; pos++)
    {
        temp = FontNumber64x32[(uint16_t)offset + pos]; // 调用64*32字体
        for (i = 0; i < 8; i++)
        {
            if (temp & 0x01)
                TFT_Write_Data16(color);
            else
                TFT_Write_Data16(BLACK);
            temp >>= 1;
        }
    }
}


void TFT_ShowNumber64(uint16_t x, uint16_t y, uint32_t num, uint8_t len, uint16_t color)
{
    uint8_t t, temp;

    for (t = 0; t < len; t++)
    {
        temp = num % 10;
        num = (num - temp) / 10;
        TFT_ShowChar64(x + ((len - 1) * 32) - (t * 32), y, temp, color);
        if (num == 0 && temp == 0)
        {
            break;
        }
    }
}


/**
 * @function: TFT_ShowChar
 * @brief 显示一个字符
 * @param {uint16_t} x：显示起点x
 * @param {uint16_t} y：显示起点y
 * @param {uint8_t} ch：要显示的字符
 * @param {uint8_t} mode：是否覆盖。叠加方式(1)还是非叠加方式(0)
 * @param {uint16_t} color：颜色
 * @return {*}
 */
void TFT_ShowChar(uint16_t x, uint16_t y, uint8_t ch, uint8_t mode, uint16_t color)
{
    uint8_t temp, pos, t;
    uint16_t x0 = x;

    if (x > TFT_WIDE - 16 || y > TFT_HIGH - 16)
        return;
    // 设置窗口
    ch = ch - ' ';                                  // 得到偏移后的值
    TFT_Address_set(x, y, x + 8 - 1, y + 16 - 1);   // 设置光标位置
    if (!mode)                                      // 非叠加方式
    {
        for (pos = 0; pos < 16; pos++)
        {
            temp = asc2_1608[(uint16_t)ch * 16 + pos]; // 调用1608字体
            for (t = 0; t < 8; t++)
            {
                if (temp & 0x01)
                    TFT_Write_Data16(color);
                else
                    TFT_Write_Data16(BLACK);
                temp >>= 1;
                x++;
            }
            x = x0;
            y++;
        }
    }
    else // 叠加方式
    {
        for (pos = 0; pos < 16; pos++)
        {
            temp = asc2_1608[(uint16_t)ch * 16 + pos]; // 调用1608字体
            for (t = 0; t < 8; t++)
            {
                if (temp & 0x01)
                    TFT_GUI_DrawPoint(x + t, y + pos, color); // 画一个点
                temp >>= 1;
            }
        }
    }
}

/**
 * @function: mypow
 * @brief 幂函数，m^n
 * @param {uint8_t} m
 * @param {uint8_t} n
 * @return {*}
 */
uint32_t mypow(uint8_t m, uint8_t n)
{
    uint32_t result = 1;
    while (n--)
        result *= m;
    return result;
}

/**
 * @function: TFT_ShowNum
 * @brief 显示数字
 * @param {uint16_t} x：显示起点x
 * @param {uint16_t} y：显示起点y
 * @param {uint32_t} num：要显示的数字
 * @param {uint8_t} len：长度
 * @param {uint16_t} colorcolor：颜色
 * @return {*}
 */
void TFT_ShowNum(uint16_t x, uint16_t y, uint32_t num, uint8_t len, uint16_t color)
{
    uint8_t t, temp, enshow = 0;
    num = (uint16_t)num;
    for (t = 0; t < len; t++)
    {
        temp = (num / mypow(10, len - t - 1)) % 10;
        if (enshow == 0 && t < (len - 1))
        {
            if (temp == 0)
            {
                TFT_ShowChar(x + 8 * t, y, ' ', 0, color);
                continue;
            }
            else
                enshow = 1;
        }
        TFT_ShowChar(x + 8 * t, y, temp + 48, 0, color);
    }
}

/**
 * @function: TFT_ShowString
 * @brief 显示字符串
 * @param {uint16_t} x：显示起点x
 * @param {uint16_t} y：显示起点y
 * @param {uint8_t} *p：字符串
 * @param {uint16_t} color：颜色
 * @return {*}
 */
void TFT_ShowString(uint16_t x, uint16_t y, const uint8_t *p, uint16_t color)
{
    while (*p != '\0')
    {
        if (x > TFT_WIDE - 16)
        {
            x = 0;
            y += 16;
        }
        if (y > TFT_HIGH - 16)
        {
            y = x = 0;
            TFT_GUI_Clear(RED);
        }
        TFT_ShowChar(x, y, *p, 0, color);
        x += 8;
        p++;
    }
}

/**
 * @function: TFT_ShowImage
 * @brief 显示一张图片
 * @param {uint16_t} x：起点x
 * @param {uint16_t} y：起点y
 * @param {uint8_t} *image：图片数据
 * @return {*}
 */
void TFT_ShowImage(uint16_t x, uint16_t y, const uint8_t *image)
{
    uint16_t i, j, k;

    for (k = 2; k < 6; k++)
    {
        for (j = 0; j < 6; j++)
        {
            TFT_Address_set(40 * j, 40 * k, 40 * j + 39, 40 * k + 39); // 坐标设置
            for (i = 0; i < 1600; i++)
            {

                TFT_Write_Data8(image[i * 2 + 1]);
                TFT_Write_Data8(image[i * 2]);
            }
        }
    }
}
